package com.mkx.application.service;

import com.mkx.application.dto.UserDTO;
import com.mkx.application.dto.TenantUserDTO;
import com.mkx.application.dto.request.CreateUserRequest;
import com.mkx.application.dto.request.UpdateUserRequest;
import com.mkx.application.dto.request.ChangePasswordRequest;
import com.mkx.application.dto.request.CreateTenantUserRequest;
import com.mkx.domain.entity.User;
import com.mkx.domain.entity.TenantUser;
import com.mkx.domain.repository.UserRepository;
import com.mkx.domain.repository.TenantUserRepository;
import com.mkx.domain.service.UserDomainService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户应用服务
 * 处理用户相关的应用层业务逻辑
 */
@Service
public class UserApplicationService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private TenantUserRepository tenantUserRepository;
    
    @Autowired
    private UserDomainService userDomainService;
    
    /**
     * 创建用户
     */
    @Transactional
    public UserDTO createUser(CreateUserRequest request) {
        // 检查用户名、邮箱、手机号是否已存在
        checkUserExists(request.getUsername(), request.getEmail(), request.getPhone());
        
        // 使用领域服务创建用户
        User user = userDomainService.createUser(
                request.getUsername(),
                request.getPassword(),
                request.getEmail(),
                request.getPhone()
        );
        
        // 保存用户
        User savedUser = userRepository.save(user);
        
        // 转换为DTO
        return toUserDTO(savedUser);
    }
    
    /**
     * 更新用户信息
     */
    @Transactional
    public UserDTO updateUser(String userId, UpdateUserRequest request) {
        // 查找用户
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        // 检查更新的字段是否与其他用户冲突
        if (request.getUsername() != null && !request.getUsername().equals(user.getUsername())) {
            if (userRepository.existsByUsername(request.getUsername())) {
                throw new IllegalArgumentException("用户名已存在");
            }
        }
        
        if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
            if (userRepository.existsByEmail(request.getEmail())) {
                throw new IllegalArgumentException("邮箱已存在");
            }
        }
        
        if (request.getPhone() != null && !request.getPhone().equals(user.getPhone())) {
            if (userRepository.existsByPhone(request.getPhone())) {
                throw new IllegalArgumentException("手机号已存在");
            }
        }
        
        // 更新用户信息
        user.updateInfo(
                request.getUsername() != null ? request.getUsername() : user.getUsername(),
                request.getEmail() != null ? request.getEmail() : user.getEmail(),
                request.getPhone() != null ? request.getPhone() : user.getPhone()
        );
        
        // 保存更新
        User updatedUser = userRepository.save(user);
        
        return toUserDTO(updatedUser);
    }
    
    /**
     * 修改密码
     */
    @Transactional
    public void changePassword(String userId, ChangePasswordRequest request) {
        // 查找用户
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        // 使用领域服务修改密码
        userDomainService.changePassword(
                user,
                request.getOldPassword(),
                request.getNewPassword()
        );
        
        // 保存更新
        userRepository.save(user);
    }
    
    /**
     * 获取用户详情
     */
    public UserDTO getUserById(String userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        return toUserDTO(user);
    }
    
    /**
     * 删除用户
     */
    @Transactional
    public void deleteUser(String userId) {
        // 检查用户是否存在
        if (!userRepository.existsById(userId)) {
            throw new IllegalArgumentException("用户不存在");
        }
        
        // 删除用户在所有租户中的关联
        tenantUserRepository.deleteByUserId(userId);
        
        // 删除用户
        userRepository.deleteById(userId);
    }
    
    /**
     * 分页查询用户
     */
    public List<UserDTO> findUsers(int page, int size) {
        List<User> users = userRepository.findAll(page, size);
        return users.stream()
                .map(this::toUserDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 创建租户用户关联
     */
    @Transactional
    public TenantUserDTO createTenantUser(CreateTenantUserRequest request) {
        // 验证请求参数
        validateIdFormat(request.getTenantId(), "租户ID");
        validateIdFormat(request.getUserId(), "用户ID");
        validateIdFormat(request.getRoleId(), "角色ID");
        
        // 检查用户是否存在
        if (!userRepository.existsById(request.getUserId())) {
            throw new IllegalArgumentException("用户不存在");
        }
        
        // 检查关联是否已存在
        if (tenantUserRepository.existsByTenantIdAndUserId(request.getTenantId(), request.getUserId())) {
            throw new IllegalArgumentException("用户已在该租户中");
        }
        
        // 使用领域服务创建租户用户关联
        TenantUser tenantUser = userDomainService.createTenantUser(
                request.getTenantId(),
                request.getUserId(),
                request.getRoleId()
        );
        
        // 保存关联
        TenantUser savedTenantUser = tenantUserRepository.save(tenantUser);
        
        // 获取用户信息
        User user = userRepository.findById(request.getUserId())
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        return toTenantUserDTO(savedTenantUser, user);
    }
    
    /**
     * 更新用户在租户中的角色
     */
    @Transactional
    public TenantUserDTO updateTenantUserRole(String tenantId, String userId, String roleId) {
        // 查找关联
        TenantUser tenantUser = tenantUserRepository.findByTenantIdAndUserId(tenantId, userId)
                .orElseThrow(() -> new IllegalArgumentException("用户在该租户中不存在"));
        
        // 更新角色
        tenantUser.updateRole(roleId);
        
        // 保存更新
        TenantUser updatedTenantUser = tenantUserRepository.save(tenantUser);
        
        // 获取用户信息
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        return toTenantUserDTO(updatedTenantUser, user);
    }
    
    /**
     * 删除租户用户关联
     */
    @Transactional
    public void deleteTenantUser(String tenantId, String userId) {
        if (!tenantUserRepository.deleteByTenantIdAndUserId(tenantId, userId)) {
            throw new IllegalArgumentException("用户在该租户中不存在");
        }
    }
    
    /**
     * 查询租户下的所有用户
     */
    public List<TenantUserDTO> findTenantUsers(String tenantId) {
        List<TenantUser> tenantUsers = tenantUserRepository.findByTenantId(tenantId);
        
        return tenantUsers.stream()
                .map(tenantUser -> {
                    User user = userRepository.findById(tenantUser.getUserId())
                            .orElseThrow(() -> new IllegalArgumentException("用户不存在: " + tenantUser.getUserId()));
                    return toTenantUserDTO(tenantUser, user);
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 分页查询租户下的用户（返回UserDTO列表）
     * 用于租户端查询用户列表
     */
    public List<UserDTO> findUsersByTenant(String tenantId, int page, int size) {
        // 验证租户ID格式
        validateIdFormat(tenantId, "租户ID");
        
        // 查询租户下的用户关联关系（分页）
        List<TenantUser> tenantUsers = tenantUserRepository.findByTenantId(tenantId, page, size);
        
        // 获取用户ID列表
        List<String> userIds = tenantUsers.stream()
                .map(TenantUser::getUserId)
                .collect(Collectors.toList());
        
        // 查询用户信息
        List<User> users = userRepository.findByIds(userIds);
        
        // 转换为DTO
        return users.stream()
                .map(this::toUserDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 检查用户是否存在
     */
    private void checkUserExists(String username, String email, String phone) {
        if (userRepository.existsByUsername(username)) {
            throw new IllegalArgumentException("用户名已存在");
        }
        if (userRepository.existsByEmail(email)) {
            throw new IllegalArgumentException("邮箱已存在");
        }
        if (userRepository.existsByPhone(phone)) {
            throw new IllegalArgumentException("手机号已存在");
        }
    }
    
    /**
     * 验证ID格式
     */
    private void validateIdFormat(String id, String idType) {
        try {
            java.util.UUID.fromString(id);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException(idType + "格式无效");
        }
    }
    
    /**
     * 转换用户实体为DTO
     */
    private UserDTO toUserDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setEmail(user.getEmail());
        dto.setPhone(user.getPhone());
        dto.setCreatedTime(user.getCreatedTime());
        dto.setUpdatedTime(user.getUpdatedTime());
        return dto;
    }
    
    /**
     * 转换租户用户实体为DTO
     */
    private TenantUserDTO toTenantUserDTO(TenantUser tenantUser, User user) {
        TenantUserDTO dto = new TenantUserDTO();
        dto.setId(tenantUser.getId());
        dto.setTenantId(tenantUser.getTenantId());
        dto.setUserId(tenantUser.getUserId());
        dto.setRoleId(tenantUser.getRoleId());
        dto.setCreatedTime(tenantUser.getCreatedTime());
        dto.setUpdatedTime(tenantUser.getUpdatedTime());
        dto.setUser(toUserDTO(user));
        return dto;
    }
}